package com.zhucai.credit.service.impl.transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.zhucai.credit.bean.CreditInvoice;
import com.zhucai.credit.bean.CreditRecord;
import com.zhucai.credit.bean.EntAccount;
import com.zhucai.credit.bean.EntCrProd;
import com.zhucai.credit.common.CommonEnums.CrAprovalStatus;
import com.zhucai.credit.common.CommonEnums.CreditStatus;
import com.zhucai.credit.common.CommonEnums.CreditUnusualStatus;
import com.zhucai.credit.common.CommonEnums.EnCrStatus;
import com.zhucai.credit.common.CommonEnums.EntType;
import com.zhucai.credit.common.CommonEnums.OperType;
import com.zhucai.credit.common.CommonEnums.ZhuCaiProdType;
import com.zhucai.credit.common.HelpConstant;
import com.zhucai.credit.common.ZhucaiConstant;
import com.zhucai.credit.model.CreditApplicationEntity;
import com.zhucai.credit.model.CreditInvoiceEntity;
import com.zhucai.credit.model.CreditRecordEntrity;
import com.zhucai.credit.model.EntAccountEntity;
import com.zhucai.credit.model.EntCrProdEntity;
import com.zhucai.credit.model.OperRecordEntity;
import com.zhucai.credit.model.PaymentPlanEntity;
import com.zhucai.credit.monitor.service.INotificationService;
import com.zhucai.credit.repository.CreditApplicationRepository;
import com.zhucai.credit.repository.CreditInvoiceRepository;
import com.zhucai.credit.repository.CreditProductRepository;
import com.zhucai.credit.repository.CreditRecordRepository;
import com.zhucai.credit.repository.EntAccountRepository;
import com.zhucai.credit.repository.EntCrProdEntityRepository;
import com.zhucai.credit.repository.OperRecordRepository;
import com.zhucai.credit.repository.PaymentPlanRepository;
import com.zhucai.credit.service.CreditPurchaserService;
import com.zhucai.credit.utils.TimeUtils;

/**
 * 采购商接口实现 2017年11月23日
 * 
 * @author hsg
 */
@Service("creditPurchaserService")
@com.alibaba.dubbo.config.annotation.Service(version = "1.0.0")
public class CreditPurchaserServiceImplT implements CreditPurchaserService {
	private static final Logger logger = LoggerFactory.getLogger(CreditPurchaserServiceImplT.class);
	@Autowired
	private EntAccountRepository entAccountRepository;
	@Autowired
	private CreditApplicationRepository creditApplicationRepository;
	@Autowired
	private OperRecordRepository operRecordRepository;
	@Autowired
	private CreditRecordRepository creditRecordRepository;
	@Autowired
	private CreditInvoiceRepository creditInvoiceRepository;
	@Autowired
	private CreditProductRepository creditProductRepository;
	@Autowired
	private EntCrProdEntityRepository entCrProdEntityRepository;
	@Autowired
	private PaymentPlanRepository paymentPlanRepository;
	@Autowired
	private MessageServiceImpl messageServiceImpl;
	@Autowired
	private InvoiceServiceImplT invoiceServiceImplT;
	@Autowired
	private InvoiceUtilServiceImpl invoiceUtilServiceImpl;
	@Autowired
	private CreditUserServiceUtil creditUserServiceUtil;
	@Resource(name = "EMAIL")
	private INotificationService emailINotificationService;

	/**
	 * 采购商的特权开通建行e点通
	 * 
	 * @date 2017年11月23日 @user hsg
	 */

	@Override
	public EntCrProd applyProdPur(EntCrProd ecp) {
		logger.info("### 采购商的特权开通建行e点通 start ecp = {}", ecp.toString());
		try {
			// 查询筑材金融信息
			EntAccountEntity eae = entAccountRepository.findByStatusNotAndEnterpriseIdAndEntType(HelpConstant.Status.delete, ecp.getEnterpriseId(), EntType.PURCHASER.toString());
			if (eae == null) {
				return null;
			}
			// 查询筑保通
			EntCrProdEntity ecpe = entCrProdEntityRepository.findByEnAccIdAndStatusNotAndCrPrTypeId(eae.getTid(), HelpConstant.Status.delete, ecp.getCrPrTypeId());
			if (ecpe != null) {
				ecpe.setLinkPerson(ecp.getLinkPerson());
				ecpe.setLinkTel(ecp.getLinkTel());
				Integer coo = entCrProdEntityRepository.updatePersonInfo(ecpe.getTid(), ecp.getLinkPerson(), ecp.getLinkTel());
				if (coo != 1) {
					logger.info("### 采购商的特权开通建行e点通 异常 更新返回条数不是一条 coo={}", coo);
					throw new RuntimeException("更新核心企业联系人信息异常！");
				}
			} else {
				ecpe = new EntCrProdEntity();
				ecpe.setEnAccId(eae.getTid());
				ecpe.setOrgnNum(eae.getOrgNum());
				ecpe.setZhucaiProdType(ZhuCaiProdType.ZHU_CAI_B_TONG.toString());
				ecpe.setCrProdRate(BigDecimal.ONE);
				ecpe.setCrProdRateStr("基准利率");
				ecpe.setApplyTime(new Date());
				ecpe.setEcpStatus(0);
				ecpe.setEnCrStatus(EnCrStatus.WAIT_OPEN.toString());
				ecpe.setEnterpriseId(eae.getEnterpriseId());
				ecpe.setEntType(EntType.PURCHASER.toString());
				ecpe.setLinkPerson(ecp.getLinkPerson());
				ecpe.setLinkTel(ecp.getLinkTel());
				ecpe.setModifyDescription("采购商特权申请筑保通");
				ecpe.setCrPrTypeId(ecp.getCrPrTypeId());
				entCrProdEntityRepository.save(ecpe);
			}
			BeanUtils.copyProperties(ecpe, ecp);
			return ecp;
		} catch (Exception e) {
			logger.error("采购商的筑保通申请出错err={}", e);
			return null;
		}

	}

	/**
	 * 查询采购商申请筑保通信息
	 * 
	 * @date 2017年11月23日 @user hsg
	 */
	@Override
	public EntCrProd findProdInfo(EntCrProd ecp) {
		try {
			// 查询筑保通
			EntCrProdEntity ecpe = entCrProdEntityRepository.findCrProdInfo(HelpConstant.Status.delete, ecp.getEnterpriseId(), EntType.PURCHASER.toString(), ecp.getCrPrTypeId());
			BeanUtils.copyProperties(ecpe, ecp);
			return ecp;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 查询采购商关联e点通申请的供应商id集合
	 * 
	 * @date 2017年12月6日 @user hsg
	 */
	@Override
	public List<Long> findSupList(Long purid, String entType) {
		List<Long> rsList = null;
		try {
			EntAccountEntity eae = entAccountRepository.findByStatusNotAndEnterpriseIdAndEntType(HelpConstant.Status.delete, purid, entType);
			rsList = creditApplicationRepository.findSupList(HelpConstant.Status.delete, eae.getTid());
			if (CollectionUtils.isEmpty(rsList)) {
				rsList = new ArrayList<Long>();
				rsList.add(0L);
			}
		} catch (Exception e) {
			rsList = new ArrayList<Long>();
			logger.error(e.getMessage());
			rsList.add(0L);
			return rsList;
		}

		return rsList;
	}

	// 新增操作记录
	private void addInvoiceRecord(Long recordId, String status, CreditInvoice checkTrue, Boolean checkFrom, Boolean checkResultTrue) {

		String review = "";
		String result = "";
		String resultReason = "";
		if (status.equals(CreditStatus.WAIT_CONFIRM_ZZW.toString())) {
			review = "发票信息有误，系统自动驳回";
			result = "驳回";
			if (checkTrue == null) {
				resultReason = "发票实体为null";
			} else if (checkTrue.getCheckTrueStatus().compareTo(2) == 0) {
				resultReason = "发票验真失败："+checkTrue.getRemark();
			} else if (checkTrue.getCheckTrueStatus().compareTo(2) != 0 && !checkFrom) {
				resultReason = "验票采购双方与筑材网采购双方不一致";
			}else if(checkTrue.getCheckTrueStatus().compareTo(2) != 0 && !checkResultTrue){
				resultReason = "发票信息与输入信息不一致";
			}

		} else if (status.equals(CreditStatus.WAIT_CONFIRM.toString())) {
			review = "系统自动识别通过";
			result = "通过";
		}
		OperRecordEntity ore = new OperRecordEntity();
		ore.setBizType(status);
		ore.setResultReason(resultReason);
		ore.setBizKey(status);
		ore.setOperTime(new Date());
		ore.setOperType(OperType.CONFIRM_ZZW.toString());
		ore.setOperator(0L);
		ore.setOutId(recordId);
		ore.setOperatorName("system");
		ore.setReview(review);
		ore.setResult(result);
		operRecordRepository.save(ore);
	}

	/**
	 * 采购商发起融资
	 * 
	 * @date 2017年12月8日 @user hsg
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	@Override
	public CreditRecord approveCreditRecord(CreditRecord cr) {
		logger.info("### 发起融资start cr = {}", cr.toString());
		try {
			CreditRecordEntrity cre = creditRecordRepository.findByPaymentIdAndStatusNot(cr.getPaymentId(), HelpConstant.Status.delete);
			// 筑材发票主键id
			CreditInvoiceEntity operationInvoice = invoiceUtilServiceImpl.operationInvoice(cr);
			String invoice_no_code = cr.getInvoiceCode().trim() + cr.getInvoiceNo().trim();

			String creditStatus = CreditStatus.WAIT_CONFIRM_ZZW.toString();
			// 发票自动验真
			CreditInvoice checkTrue = invoiceServiceImplT.checkTrue(cr.getInvoiceUrl(), cr.getTid());
			//验证归属
			Boolean checkFrom = invoiceServiceImplT.checkFrom(cr.getTid(), operationInvoice.getTid());
			//验证发票验真返回和输入是否一致
			CreditInvoiceEntity cie = creditInvoiceRepository.findOne(operationInvoice.getTid());
			Boolean checkResultTrue = invoiceUtilServiceImpl.checkResultTrue(cie);
			if (checkTrue != null && checkTrue.getCheckTrueStatus().equals(1) && checkFrom && checkResultTrue) {
				logger.info("### 发票验真成功，开始判断当前用户输入信息和发票验真结果是否一致 验真返回实体 CreditInvoice={}", checkTrue.toString());
				creditStatus = CreditStatus.WAIT_CONFIRM.toString();
			}

			if (cre == null || (cre.getCreditStatus().equals(CreditStatus.WAIT_SUBMIT.toString()) && cre.getCreditUnusualStatus().equals(CreditUnusualStatus.NORMAL.toString()))) {
				cre = createCreditRecordEntrity(cr);
				cre.setCreditStatus(creditStatus);
				cre.setInvoiceTid(operationInvoice.getTid());
				// 发票和发票代码的合在一起
				cre.setInvoiceNoCode(invoice_no_code);
				creditRecordRepository.saveAndFlush(cre);
			} else {
				// 资质申请记录
				CreditApplicationEntity cae = creditApplicationRepository.findCoopInfo(HelpConstant.Status.delete, cre.getParticipator(), cre.getOriginator(),
						CrAprovalStatus.BANK_SUCCESS.toString(), cre.getCrProdId());
				cre.setCreditUnusualStatus(CreditUnusualStatus.NORMAL.toString());
				cre.setRejectReason(null);
				Integer coo = creditRecordRepository.updateRecordInvoice(CreditUnusualStatus.NORMAL.toString(), null, creditStatus, operationInvoice.getTid(), invoice_no_code,
						cre.getTid(), cre.getTransactionTime(), cr.getCrProdId(), cae.getAppNum(), cae.getContractNum());
				if (coo != 1) {
					throw new RuntimeException("重新发起融资异常！");
				}
			}

			BeanUtils.copyProperties(cre, cr);

			// 更新付款计划
			PaymentPlanEntity ppe = paymentPlanRepository.findOne(cr.getPaymentId());
			paymentPlanRepository.updatePayState(ppe.getTid(), ZhucaiConstant.PaymentPlanStatus.CHECKING_PAYMENT_STATUS);

			// 新增融资记录发起的时间
			creditUserServiceUtil.createRecordTime(cre.getTid(), CreditStatus.WAIT_SUBMIT.toString());

			// 新增发票系统审核操作记录
			addInvoiceRecord(cre.getTid(), creditStatus, checkTrue, checkFrom,checkResultTrue);

			// 新增操作记录
			OperRecordEntity ope = new OperRecordEntity();
			ope.setModifyDescription("采购商发起融资");
			ope.setResult("采购商发起融资");
			ope.setReview("采购商发起融资");
			ope.setBizKey(creditStatus);
			ope.setOperator(cr.getUserId());
			ope.setOperatorName(cr.getUserName());
			ope.setOperTime(new Date());
			ope.setOperType(OperType.TRACK_CREDIT.toString());
			ope.setOutId(cre.getTid());
			operRecordRepository.save(ope);
		} catch (Exception e) {
			// TODO: handle exception
			emailINotificationService.notification("发起融资失败 融资单号=" + cr.getRecordNo());
			logger.error("### 发起融资失败 融资单号={}，err={}", cr.getRecordNo(), e);
			throw new RuntimeException("发起融资失败");
		}

		return cr;
	}

	private CreditRecordEntrity createCreditRecordEntrity(CreditRecord cr) {

		CreditRecordEntrity cre = creditRecordRepository.findByStatusNotAndPaymentId(HelpConstant.Status.delete, cr.getPaymentId());
		if (cre == null) {
			cre = new CreditRecordEntrity();
		}
		// 融资申请的金融id(采购商)
		EntAccountEntity purent = entAccountRepository.findByStatusNotAndEnterpriseIdAndEntType(HelpConstant.Status.delete, cr.getOriginatorEnterpriseId(),
				EntType.PURCHASER.toString());
		if (purent == null) {
			throw new RuntimeException("融资申请失败：查询采购商金融信息失败");
		}
		EntAccountEntity supent = entAccountRepository.findByStatusNotAndEnterpriseIdAndEntType(HelpConstant.Status.delete, cr.getParticipatorEnterpriseId(),
				EntType.SUPPLIER.toString());
		if (supent == null) {
			throw new RuntimeException("融资申请失败:查询供应商金融信息失败");
		}
		// 查询贷款资质申请记录supent.getTid()
		CreditApplicationEntity cae = creditApplicationRepository.findCoopInfo(HelpConstant.Status.delete, supent.getTid(), purent.getTid(),
				CrAprovalStatus.BANK_SUCCESS.toString(), cr.getCrProdId());

		// 报名编号
		cre.setAppNum(cae.getAppNum());
		// 贷款机构
		cre.setCrProdId(cr.getCrProdId());
		// 合同id
		cre.setContractId(cr.getContractId());
		// 合同编号
		cre.setContractNum(cr.getContractNum());
		// 账款金额
		cre.setCreditGetAmount(cr.getCreditAmount());
		// 融资金额
		cre.setCreditAmount(BigDecimal.ZERO);
		// 供应商权限cc
		cre.setPartRoleUserId(cr.getPartRoleUserId());
		// 投标发起人
		cre.setParticipatorUserId(cr.getParticipatorUserId());
		// 供应商组织机构
		cre.setParticipatorOrgnCode(supent.getOrgNum());
		// 供应商企业id
		cre.setParticipatorEnterpriseId(cr.getParticipatorEnterpriseId());
		Integer dateTian = TimeUtils.dateTian(cr.getLoanDate(), new Date());
		// 账期
		cre.setCreditPeriod(dateTian);
		// 账款到期日
		cre.setLoanDate(cr.getLoanDate());

		cre.setOriginator(purent.getTid());
		// 融资申请的用户id（采购商）
		cre.setOriginatorUserId(cr.getOriginatorUserId());
		// 采购商组织机构
		cre.setOriginatorOrgnCode(purent.getOrgNum());
		// 采购商企业id
		cre.setOriginatorEnterpriseId(cr.getOriginatorEnterpriseId());
		// 融资参与者的金融id(供应商)
		cre.setParticipator(supent.getTid());

		// 建行合同
		cre.setContractNumCcb(cae.getContractNum());
		// 付款单号
		cre.setPaymentNum(cr.getPaymentNum());
		// 付款计划id
		cre.setPaymentId(cr.getPaymentId());
		// 业务操作时间
		cre.setTransactionTime(new Date());
		// 融资编号
		cre.setRecordNo(cr.getRecordNo());
		// 融资正常状态
		cre.setCreditUnusualStatus(CreditUnusualStatus.NORMAL.toString());
		// 项目id
		cre.setProjectTid(cr.getProjectTid());

		return cre;

	}

	/**
	 * 根据企业id获取融资的计划付款id
	 */
	@Override
	public List<Long> findPlayAmountId(Long enterpriseId) {

		return creditRecordRepository.findPlayAmountId(HelpConstant.Status.delete, enterpriseId);
	}

	/**
	 * 根据银行类型查询开通此银行的筑保通的采购商列表
	 * 
	 * @version 2018年9月25日
	 * @param bankType
	 * @return
	 */
	@Override
	public List<EntAccount> searchPurEnt(String bankType, String ZhuBaoTong) {
		logger.info("### 根据银行类型查询开通此银行的筑保通的采购商列表,bankType={},ZhuBaoTong={}", bankType, ZhuBaoTong);
		List<EntAccountEntity> searchPurEnt = entAccountRepository.searchPurEnt(bankType, ZhuBaoTong, EntType.PURCHASER.toString());
		List<EntAccount> rsList = new ArrayList<EntAccount>();
		if (!CollectionUtils.isEmpty(searchPurEnt)) {
			for (EntAccountEntity entAccountE : searchPurEnt) {
				EntAccount ea = new EntAccount();
				BeanUtils.copyProperties(entAccountE, ea);
				rsList.add(ea);
			}
		}

		return rsList;
	}

}
